Kompakte matriser med roterte kolonneoverskrifter
Innimellom kommer vi over tabeller (matriser) som har et veldig kortfattet innhold i hver enkeltcelle, samtidig som at rad- og kolonneoverskriftene vil være av noe lenger art.
I slike tilfeller hadde det vært fint om kolonneoverskriftene kunne tatt minst mulig plass, slik at cellene ikke blir unødvendig brede. Hva med å rotere dem?
Å rotere noe er enkelt nok med transform: rotate()
. Her har jeg valgt å rotere kolonneoverskriftene med 45°. Særlig vakkert blir det dog ikke på første forsøk.
th {
transform: rotate(-45deg);
}
Første problem vi støter på er at skråstillingen fortsatt krever for mye bredde. Dette kan vi fikse med posisjonering. Vi innfører en indre div
og flytter rotasjonen til den.
<th><div class="roter">Ild</div></th>
<th><div class="roter">Vann</div></th>
<th><div class="roter">Gress</div></th>
th {
position: relative;
border: none;
}
.roter {
position: absolute;
bottom: 0;
transform: rotate(-45deg);
border: 1px solid white;
}
Fortsatt ser det rart ut. Dette skyldes blant annet at vi har rotert div
-ene rundt sitt eget sentrum. Vi ønsker istedet å rotere rundt et av de nedre hjørnene. Dette fikser vi greit med transform-origin
.
.roter {
/* Gammelt */
position: absolute;
bottom: 0;
transform: rotate(-45deg);
border: 1px solid white;
/* Nytt */
transform-origin: bottom left;
}
Da ser vi at hjørnet på div
-ene havner for langt til venstre, så vi må flytte dem like mye til høyre som kolonnene er brede (40 piksler).
.roter {
/* Gammelt */
position: absolute;
bottom: 0;
transform: rotate(-45deg);
border: 1px solid white;
transform-origin: bottom left;
/* Nytt */
left: 40px;
}
Neste irritasjon er at div
-ene er for lave. På øyemål ser vi at de må være lavere enn den opprinnelige cellebredden, men hvor mye?
Du spurte kanskje læreren din om hva pokker vi skal med Pytagoras, og vedkommende svarte sikkert at det skal hjelpe deg med å rotere, posisjonere og velge størrelse på roterte kolonneoverskrifter i kompakte matriser. Det hadde i hvert fall jeg svart, for han skal vi bruke nå!
Kolonnebredden er på 40px
.
Pytagoras på sin pureste form er som vi alle husker slik: hosliggende katet² + motstående katet² = hypotenus²
.
På litt kortere form: a² + b² = c²
.
Siden katetene er like lange, får vi a² + a² = c² => 2a² = c²
.
Også kan vi fylle inn for c
(kolonnebredden):
Så da ender vi til slutt opp med:
2a² = 1600
=> a² = 800
=> a = √800
=> a ≈ 28,28
Alternativ (og bedre?) trigonometrisk løsning:
sin(α) = motstående katet ÷ hypotenus // α angitt i radianer, og 45° = π/4 radianer
=> sin(π ÷ 4) = motstående katet ÷ hypotenus
=> sin(π ÷ 4) = motstående katet ÷ 40
=> motstående katet = sin(π ÷ 4) × 40
=> motstående katet ≈ 28,28
.roter {
/* Gammelt */
position: absolute;
bottom: 0;
transform: rotate(-45deg);
border: 1px solid white;
transform-origin: bottom left;
left: 40px;
/* Nytt */
height: 28.28
}
Men hva om vi har rotert med noe annet enn 45°, sier du? La oss si at vi istedet ønsker å rotere med 33°. Vi gjenbruker den alternative trigonometriske løsningen.
33° = 2π × (33 ÷ 360) radianer
sin(2π × 33 ÷ 360) = høyde ÷ 40
=> sin(2π × 33 ÷ 360) × 40 = høyde
=> høyde ≈ 21,79
.roter {
/* Gammelt */
position: absolute;
bottom: 0;
border: 1px solid white;
transform-origin: bottom left;
left: 40px;
/* Nytt */
transform: rotate(-33deg);
height: 21.79
}
Men tilbake til 45°-løsningen.
Så hadde det jo vært fryktelig fint om det ikke var et “åpent hakk” mellom linjene til tbody
-en og linjene til overskriftene. Vi trenger å strekke dem ut på et eller annet vis. Hva med transform: skew()
?
Vi innfører en ny div
, hvis oppgave er å tegne et parallellogram rundt de roterte overskriftene.
Dette medfører dessverre at vi mister muligheten til å ha dynamisk størrelse på overskriftene, så vi hardkorder dette til 60 piksler (inntil videre).
.roter {
/* Gammelt */
position: absolute;
bottom: 0;
transform: rotate(-45deg);
transform-origin: bottom left;
left: 40px;
/* Fjernet */
/* height: 28.29px; */
/* border: 1px solid white; */
/* Nytt */
border: none;
}
.skew {
transform-origin: bottom left;
transform: skew(-45deg);
border: 1px solid white;
width: 40px;
bottom: 0;
height: 60px;
}
Vi ser nå at tekstene er både forvrengt og overrotert. Dette skyldes at vi også har skew
-et innholdet i roter
-div
-en, noe som ikke er ønskelig. Vi legger derfor inn en "anti"-skew
i den indre roterte div
-en.
.roter {
/* Gammelt */
position: absolute;
bottom: 0;
transform-origin: bottom left;
left: 40px;
border: none;
/* Nytt */
transform: skew(45deg) rotate(-45deg);
}
Så har vi som nevnt juksa litt ved å sette en fast høyde på div
-en medskew
. Hva skjer om vi fjerner dette igjen?
.skew {
/* Gammelt */
transform-origin: bottom left;
transform: skew(-45deg);
border: 1px solid white;
width: 40px;
/* Nytt */
height: auto;
border: 1px solid red;
}
Da blir skew
-høyden 0, og her er det slutt på de gode løsningene. Hvis man ikke har ønske om eller mulighet til å benytte fast høyde, kan dette løses med JavaScript.
const roterteDiver = document.querySelectorAll('.roter');
const bredder = [...roterteDiver].map(({ offsetWidth }) => offsetWidth);
const høyde = Math.max(...bredder);
document.querySelectorAll('.skew').forEach(({ style }) => {
style.height = høyde + 'px';
});
Og hvis du synes dette ble for ille og har gitt opp alt håpet for 45° roterte overskrifter, så kan jeg forsøke å trøste deg med at det finnes en noe enklere °.-løsning.
thead th {
writing-mode: vertical-lr;
/* writing-mode: sideways-lr; */ /* Finest, men foreløpig kun støttet i Firefox */
}
Håper dette var nyttig lesing og læring!
Er du nysgjerrig på hvilke muligheter vi har for deg i Systek, sjekk gjerne ut våre tjenester og ledige stillinger på https://systek.no/.